---
sidebar_position: 2
---

# IExcelReader

:::info
由于使用了 `NPOI,EPPlus,MiniExcel` 三种实现, 所以简单封装了一个 `IExcelReader`, 试图简化使用

暂时来看是有效果的，对我来说效果非常好
:::

## 接口定义

:::info
`IExcelReader` 的定义类似下面这样
:::

```csharp
public interface IExcelReader<T> : IDisposable
{
    IEnumerable<T> this[string field] { get; }
    IEnumerable<T> this[long row] { get; }
    T this[long row, long col] { get; }
    T this[string field, long row] { get; }
    IEnumerable<string> Headers { get; }
    IDictionary<string, int> HeadersWithIndex { get; }
    long RowCount { get; }
}
```

为了方便使用, 又有

```csharp
public interface IExcelReader : IExcelReader<string> { }
```

会将 excel 中的所有数据都 `ToString`

:::tip
最佳实践中的导入功能就是依据 IExcelReader 实现的
:::

## 获取 IExcelReader 实例

:::note
现阶段拥有 `NPOIExcelReader EPPlusExcelRead MiniExcelReader` 三种实现
:::

```csharp
using IExcelReader reader = new NPOIExcelReader(filePath);
using IExcelReader reader = new EPPlusExcelRead(filePath);
using IExcelReader reader = new MiniExcelReader(filePath);
```

## 使用

### 获取单元格的值

```csharp
// 第 1 行 第 6 列
string value = reader[0, 5];
```

### 获取行

```csharp
var row = read[0];
```

### 获取列

:::info
我认为"列"与"行"不同, 是不适合直接用下标去获取的, 所以设计成传有"含义"的列名称
:::

```csharp
IEnumerable<string> col = read["Column"];
```

:::caution
尝试使用`yield return` 降低性能损耗, 但是有没有效果, 有多大效果, 这我就不知道了, 暂时也没有能力去验证
:::
:::danger
MiniExcelReader 由于 MiniExcel 的实现问题，在获取超出原表格范围的单元格数据时，可能会出现异常
:::

## 实现了 IEnumerable

:::note
花了点时间实现了 IEnumerable 接口

数据类型为 `IEnumerable<string>`

现在 `IExcelReader` 支持使用 First() Last() 等集合方法了!
:::

```csharp
IExcelReader reader = new MiniExcelReader(path);
reader.Count();
var IEnumerable<string> firstData = reader.First();
var IEnumerable<string> lastData = reader.Last();
var IEnumerable<string> skipOne = reader.Skip(1).First()
```

:::tip
由于实现了 `IEnumerable`，所以也可以使用一些 `Collapsenav.Net.Tool` 的方法
:::

```csharp
IExcelReader reader = new MiniExcelReader(path);
IEnumerable<string> mergeData = reader.Merge()
```

:::caution
由于实现问题，有些操作无法使用，比如 `AddRange` 之类存在修改操作的方法

后面可能会做这些方便的实现
:::
